﻿using System;
using System.Drawing;
using System.Runtime.InteropServices.APIs;

namespace Useful.GUI
{
    public class GDI
    {
        public enum FillType
        {
            FLOODFILLBORDER = 0,
            FLOODFILLSURFACE = 1
        }

        private static void Fill(Graphics g, Point pos, Color bounds, Color fill, ref Bitmap bmp, FillType fillType)
        {
            uint ft;

            switch (fillType)
            {
                case FillType.FLOODFILLBORDER: ft = APIsGdi.FLOODFILLBORDER; break;
                case FillType.FLOODFILLSURFACE: ft = APIsGdi.FLOODFILLSURFACE; break;
                default: throw new ArgumentOutOfRangeException();
            }

            IntPtr lDC = g.GetHdc();

            IntPtr memDC = APIsGdi.CreateCompatibleDC(lDC);

            IntPtr hBrush = APIsGdi.CreateSolidBrush((uint)ColorTranslator.ToWin32(fill));
            IntPtr hOldBr = APIsGdi.SelectObject(memDC, hBrush);

            IntPtr hBMP = bmp.GetHbitmap();
            IntPtr hOldBmp = APIsGdi.SelectObject(memDC, hBMP);

            APIsGdi.ExtFloodFill(memDC, pos.X, pos.Y, (uint)ColorTranslator.ToWin32(bounds), ft);

            // Записываем полученный залитый битмап в наш битмап
            bmp.Dispose();
            bmp = Image.FromHbitmap(hBMP);

            APIsGdi.SelectObject(memDC, hOldBr);
            APIsGdi.SelectObject(memDC, hOldBmp);

            APIsGdi.DeleteObject(hBMP);
            APIsGdi.DeleteObject(hBrush);
            APIsGdi.DeleteObject(memDC);

            g.ReleaseHdc(lDC);
        }

        public static void FillToBorder(Graphics g, Point pos, Color bounds, Color fill, ref Bitmap bmp)
        {
            Fill(g, pos, bounds, fill, ref bmp, FillType.FLOODFILLBORDER);
        }

        public static void FillSurface(Graphics g, Point pos, Color bounds, Color fill, ref Bitmap bmp)
        {
            Fill(g, pos, bounds, fill, ref bmp, FillType.FLOODFILLSURFACE);
        }

        public static Bitmap ReplaceColor(Bitmap bitmap, Color c)
        {
            for (int x = 0; x < bitmap.Width; x++)
            {
                for (int y = 0; y < bitmap.Height; y++)
                {
                    if (bitmap.GetPixel(x,y).ToArgb() != Color.Empty.ToArgb())
                        bitmap.SetPixel(x, y, c);
                }
            }

            return bitmap;
        }

        public static Bitmap GetBitmap(Bitmap image, Rectangle r, Color color)
        {
            Bitmap res = new Bitmap(r.Size.Width, r.Size.Height);

            for (int x = r.Left; x < r.Right; x++ )
            {
                for (int y = r.Top; y < r.Bottom; y++)
                {
                    Color c = image.GetPixel(x,y);

                    if (c.ToArgb() == color.ToArgb())
                        res.SetPixel(x - r.Left, y - r.Top, c);
                    else
                        res.SetPixel(x - r.Left, y - r.Top, Color.Transparent);
                }
            }

            return res;
        }

        public static Bitmap ScreenShot(Rectangle rect)
        {
            Bitmap bitmap = new Bitmap(rect.Width, rect.Height);

            using (Graphics bmpGraphics = Graphics.FromImage(bitmap))
                bmpGraphics.CopyFromScreen(rect.X, rect.Y, 0, 0, new Size(rect.Width, rect.Height));

            return bitmap;
        }

        public static void ImageToScreen(IntPtr windowHandle, Point location, Image img)
        {
            IntPtr destDeviceContext = APIsGdi.GetDC(windowHandle);

            using (Graphics g = Graphics.FromHdc(destDeviceContext))
            {
                g.DrawImage(img, location);
            }
        }
    }
}